// 添加必要的导入
const path = require('path');
const fs = require('fs');

const axios = require('axios');


const ffmpeg = require('fluent-ffmpeg');
const ffmpegPath = require('@ffmpeg-installer/ffmpeg').path;
const ffprobeStatic = require('ffprobe-static').path;

console.log('ffmpegPath:', ffmpegPath);
console.log('ffprobeStatic:', ffprobeStatic);
// 设置FFmpeg和FFprobe路径
ffmpeg.setFfmpegPath(ffmpegPath);
ffmpeg.setFfprobePath(ffprobeStatic);

// 设置文件临时下载目录
const outputPath = path.resolve('output', 'video');
if (!fs.existsSync(outputPath)) {
    fs.mkdirSync(outputPath, { recursive: true });
}




/**
 * 将生成的视频发送到指定URL
 * @async
 * @function sendResultToUrl
 * @param {Buffer} buffer - 视频文件缓冲区
 * @param {string} [fileName='output.mp4'] - 文件名
 * @returns {Promise<Object>} - 上传结果
 * @throws {Error} - 上传失败时抛出错误
 */
async function sendResultToUrl(buffer, fileName = 'output.mp4') {
    try {
        const APIURL = 'https://env-00jxgx7alqyz.dev-hz.cloudbasefunction.cn/upload_file';
        const FormData = require('form-data');

        const form = new FormData();
        form.append('file', buffer, fileName);

        const response = await axios.post(APIURL, form, {
            headers: {
                ...form.getHeaders(),
                'Content-Length': form.getLengthSync()
            }
        });

        // 直接返回云端的完整结果
        return response.data;
    } catch (error) {
        console.error('发送失败:', error.message);
        return { code: 500, message: error.message };
    }
}



/**
 * 格式化字幕文本
 * @param {string} text - 原始字幕文本
 * @returns {string} - 格式化后的字幕文本
 */
function formatSubtitleText(text) {
    if (!text || typeof text !== 'string') {
        console.error('字幕文本不能为空且必须是字符串');
        return '';
    }

    // 去除换行符
    text = text.replace(/\n/g, '');
    const endings = ['。', '！', '？', '.', '!', '?'];
    let lines = [];
    let start = 0;

    // 按句子分割
    for (let i = 0; i < text.length; i++) {
        if (endings.includes(text[i])) {
            const sentence = text.slice(start, i + 1);
            // 如果句子过长，按词分割
            if (sentence.length > 15) {
                const words = sentence.split('');
                let currentLine = '';
                for (const word of words) {
                    // 根据行号设置最大长度
                    const maxLength = lines.length === 0 ? 15 :
                        lines.length === 1 ? 14 : 13;
                    if ((currentLine + word).length <= maxLength) {
                        currentLine += word;
                    } else {
                        lines.push(currentLine);
                        currentLine = word;
                        // 如果已经达到3行，则停止添加
                        if (lines.length >= 3) break;
                    }
                }
                if (currentLine && lines.length < 3) {
                    lines.push(currentLine);
                }
            } else {
                if (lines.length < 3) {
                    lines.push(sentence);
                }
            }
            start = i + 1;
            if (lines.length >= 3) break;
        }
    }

    // 处理最后未结束的句子
    if (start < text.length && lines.length < 3) {
        const last = text.slice(start);
        if (last.length > 0) {
            const words = last.split('');
            let currentLine = '';
            for (const word of words) {
                const maxLength = lines.length === 0 ? 15 :
                    lines.length === 1 ? 14 : 13;
                if ((currentLine + word).length <= maxLength) {
                    currentLine += word;
                } else {
                    if (lines.length < 2) {
                        lines.push(currentLine);
                        currentLine = word;
                    }
                }
                if (lines.length >= 2) break;
            }
            if (currentLine && lines.length < 2) {
                lines.push(currentLine);
            }
        }
    }

    // 确保每行不超过最大长度
    lines = lines.map((line, index) => {
        const maxLength = index === 0 ? 15 :
            index === 1 ? 14 : 13;
        return line.length > maxLength ? line.slice(0, maxLength) + '...' : line;
    });

    const result = lines.join('\n');
    console.log('格式化后的字幕：', result);
    return result;
}


/**
 * 将图片、音频和字幕合成为视频
 * @async
 * @function textAndImgAndAudioToVideo
 * @param {Object} options - 配置选项
 * @param {string} [options.outputName=`output_${Date.now()}.mp4`] - 输出视频文件名
 * @param {string} options.imagePath - 图片路径或URL
 * @param {string} options.audioPath - 音频路径或URL
 * @param {string} [options.topSubtitleText=''] - 上方字幕文本
 * @param {string} [options.bottomSubtitleText=''] - 下方字幕文本
 * @returns {Promise<Object>} - 返回包含视频信息和上传结果的对象
 * @throws {Error} - 视频生成失败时抛出错误
 * @example
 * const result = await textAndImgAndAudioToVideo({
 *   imagePath: 'https://example.com/image.png',
 *   audioPath: 'https://example.com/audio.mp3',
 *   outputName: 'output.mp4',
 *   topSubtitleText: '上方字幕',
 *   bottomSubtitleText: '下方字幕'
 * });
 */
async function textAndImgAndAudioToVideo(options) {

    
    let {
        outputName = `output_${Date.now()}.mp4`,
        imagePath,
        audioPath,
        topSubtitleText = '',
        bottomSubtitleText = '',
    } = options;


    // 修复：将 outputPath 的定义移到函数顶部
    const outputDir = path.dirname(outputPath);
    const finalOutputPath = path.resolve(outputDir, outputName);  // 重命名避免冲突

    // 确保输出目录存在
    if (!fs.existsSync(outputDir)) {
        fs.mkdirSync(outputDir, { recursive: true });
    }

    // 添加类型检查
    if (typeof imagePath !== 'string') {
        imagePath = String(imagePath);
    }
    if (typeof audioPath !== 'string') {
        audioPath = String(audioPath);
    }

    // 检查输入参数
    if (!imagePath || !audioPath) {
        console.error('未输入图片或音频,程序无法运行');
        return false;
    }

    // 如果输入的图片是url,则需要下载到本地
    if (imagePath.startsWith('http')) {
        const tempImgPath = path.resolve(outputDir, `temp_${Date.now()}.png`);
        const response = await axios.get(imagePath, { responseType: 'arraybuffer' });
        const arrayBuffer = response.data;

        // 根据响应头来判断图片的格式,如果没有,默认是 png
        const contentType = response.headers['content-type'];
        console.log('contentType:', contentType);
        fs.writeFileSync(tempImgPath, Buffer.from(arrayBuffer));
        imagePath = tempImgPath;
    }

    // 如果输入的音频是url,则需要下载到本地
    if (audioPath.startsWith('http')) {
        const tempAudioPath = path.resolve(outputDir, `temp_${Date.now()}.mp3`);
        const response = await axios.get(audioPath, { responseType: 'arraybuffer' });
        const arrayBuffer = response.data;

        // 根据响应头来判断音频的格式,如果没有,默认是 mp3
        const contentType = response.headers['content-type'];
        console.log('contentType:', contentType);
        fs.writeFileSync(tempAudioPath, Buffer.from(arrayBuffer));
        audioPath = tempAudioPath;
    }

    try {
        console.log('开始生成视频...');
        const startTime = Date.now();

        console.log('[步骤1/6] 正在获取音频时长...');
        const audioDuration = await getAudioDuration(audioPath);
        console.log(`✅ 音频时长获取成功: ${audioDuration}秒`);

        console.log('[步骤2/6] 正在格式化字幕文本...');
        const formattedTopSubtitle = topSubtitleText;
        const formattedBottomSubtitle = formatSubtitleText(bottomSubtitleText);
        console.log('✅ 字幕文本格式化完成');

        console.log('[步骤3/6] 正在构建滤镜参数...');
        const filterComplex = [
            `[1:v]scale=1080:-1,setsar=1,pad=1080:1920:(ow-iw)/2:(oh-ih)/2:black[v];`,
            // 添加上方字幕
            `[v]drawtext=text='${formattedTopSubtitle.replace(/'/g, "\\'")}':`,
            `fontcolor=white:fontsize=80:x=(w-text_w)/2:y=300:`,  // 修改x和y参数
            `box=1:boxcolor=#FF9900@0.8:boxborderw=5:line_spacing=10:`,  // 设置字幕背景颜色为 #FA8919
            `borderw=2:bordercolor=0x000000@0.5:`,
            `shadowcolor=black@0.8:shadowx=2:shadowy=2:`,
            `bordercolor=black@0.5:borderw=2:`,
            `enable='between(t,0,${audioDuration})'[v1];`,
            // 添加下方字幕
            `[v1]drawtext=text='${formattedBottomSubtitle.replace(/'/g, "\\'")}':`,
            `fontcolor=white:fontsize=58:x=(w-text_w)/2:y=1380:`,  // 修改x和y参数
            `box=1:boxcolor=0x000000@0.5:boxborderw=5:line_spacing=10:`,
            `borderw=2:bordercolor=0x000000@0.5:`,
            `shadowcolor=black@0.8:shadowx=2:shadowy=2:`,
            `bordercolor=black@0.5:borderw=2:`,
            `enable='between(t,0,${audioDuration})'[vt];`,
            `[0:a]anull[a]`
        ].join('');
        console.log('✅ 滤镜参数构建完成');

        console.log('[步骤4/6] 正在初始化FFmpeg命令...');
        await new Promise((resolve, reject) => {
            const command = ffmpeg()
                .input(audioPath)
                .input(imagePath)
                .inputOptions([
                    '-t', audioDuration
                ])
                .complexFilter([
                    'loop=loop=-1:size=1',  // 将-loop参数改为complexFilter
                    // ... existing filter complex code ...
                ])
                .outputOptions([
                    // 添加滤镜
                    '-filter_complex', filterComplex,
                    // 映射视频流和音频流
                    '-map', '[vt]',
                    '-map', '[a]',
                    // 设置分辨率和帧率
                    '-s', '1080x1920',
                    '-r', '30',
                    // 设置视频比特率,可选参数: 10M, 5M, 2M, 1M, 500k, 250k, 125k, 64k
                    '-b:v', '10M',
                    // 设置视频编码,可选参数: libx264, libx265, mpeg4, vp9, prores, h264_nvenc, hevc_nvenc
                    '-c:v', 'libx264',
                    // 设置音频比特率,可选参数: 128k, 64k, 32k
                    '-b:a', '128k',
                    // 设置音频编码器,可选参数: aac, mp3, ac3, eac3
                    '-c:a', 'mp3',
                    // 添加preset参数加快编码速度, 可选 superfast, ultrafast, veryfast, faster, fast, medium, slow, slower, veryslow
                    '-preset', 'medium',
                    // 使用多线程加速
                    '-threads', '16',
                    // 添加快速解码优化
                    '-tune', 'fastdecode',
                    // 确保视频在音频结束时结束
                    '-shortest',
                    '-pix_fmt', 'yuv420p'
                ])
                .output(finalOutputPath)
                .on('start', (commandLine) => {
                    console.log('[步骤5/6] FFmpeg命令已启动，开始视频编码...');
                })
                .on('progress', (progress) => {
                    console.log(`🔄 编码进度: ${Math.floor(progress.percent)}%`);
                })
                .on('end', () => {
                    console.log('[步骤6/6] 视频编码完成，正在验证视频文件...');
                    ffmpeg.ffprobe(finalOutputPath, (err, metadata) => {
                        if (err) {
                            console.error('❌ 视频验证失败:', err);
                        } else {
                            const duration = metadata.format.duration;
                            const minutes = Math.floor(duration / 60);
                            const seconds = Math.floor(duration % 60);
                            console.log(`✅ 视频验证成功，总时长: ${minutes}分${seconds}秒`);
                        }
                        resolve();
                    });
                })
                .on('error', (err) => {
                    console.error('❌ 视频生成失败:', err);
                    reject(err);
                })
                .run();
        });


        let res = null;
        try {
            console.log('视频生成完成，准备上传 unicloud 云端');
            const videoBuffer = fs.readFileSync(finalOutputPath);  // 使用 config.outputName
            res = await sendResultToUrl(videoBuffer, outputName);
            console.log('上传结果:', res);

        } catch (error) {
            return {
                code: 500,
                message: "转换失败",
                data: error || null
            };
        }

        if (res.code === 200) {
            // 删除本地视频文件
            fs.unlinkSync(finalOutputPath);
            console.log('✅ 本地视频文件已删除');
        }

        // 视频生成成功后，删除临时文件
        if (imagePath && fs.existsSync(imagePath)) {
            fs.unlinkSync(imagePath);
            console.log('✅ 临时图片文件已删除');
        }
        if (audioPath && fs.existsSync(audioPath)) {
            fs.unlinkSync(audioPath);
            console.log('✅ 临时音频文件已删除');
        }

        const endTime = Date.now();
        const duration = (endTime - startTime) / 1000;
        const minutes = Math.floor(duration / 60);
        const seconds = Math.floor(duration % 60);
        console.log(`🎉 视频生成成功，总用时: ${minutes}分${seconds}秒`);

        return {
            ...res,
            inputData: {
                imagePath,
                audioPath,
                outputName,
                topSubtitleText,
                bottomSubtitleText
            }
        }

    } catch (error) {
        console.error('❌ 视频生成失败:', error);
        // 如果出错，也要尝试删除临时文件

        if (finalOutputPath && fs.existsSync(finalOutputPath)) {
            fs.unlinkSync(finalOutputPath);
            console.log('✅ 临时视频文件已删除');
        }

        if (imagePath && fs.existsSync(imagePath)) {
            fs.unlinkSync(imagePath);
            console.log('✅ 临时图片文件已删除');
        }
        if (audioPath && fs.existsSync(audioPath)) {
            fs.unlinkSync(audioPath);
            console.log('✅ 临时音频文件已删除');
        }
        throw error;
    }
}

// 获取音频时长的函数
async function getAudioDuration(audioPath) {
    console.log(`正在分析音频文件: ${audioPath}`);
    return new Promise((resolve, reject) => {
        ffmpeg.ffprobe(audioPath, (err, metadata) => {
            if (err) {
                console.error('获取音频时长失败:', err);
                return reject(err);
            }
            console.log('音频时长获取成功');
            resolve(metadata.format.duration);
        });
    });
}






// 导出
module.exports = {
    textAndImgAndAudioToVideo
}



if (require.main === module) {
    // 生成片头视频片段
    textAndImgAndAudioToVideo({
        // 输出名称
        outputName: 'temp_head_video.mp4',
        // 海报地址
        imagePath: 'https://env-00jxgx7alqyz.normal.cloudstatic.cn/demo.mp4?expire_at=1739951100&er_sign=bf3f70d8d1936c699b168c322ab6fde3',
        // 音频地址
        audioPath: 'https://env-00jxgx7alqyz.normal.cloudstatic.cn/background.mp3?expire_at=1739955378&er_sign=f91a24babaa78b382397451223fb88d7',
        // 上方字幕
        topSubtitleText: '2025年2月19日今日资讯',
        // 下方字幕
        bottomSubtitleText: '这是一段很长很长的内容描述···'
    }).then(res => {
        console.log('视频生成成功:', res);
    }).catch(err => {
        console.error('视频生成失败:', err);
    });
}